package com.example.Cairodio;

import java.util.ArrayList;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.example.entities.Place;

/**
 * @author Mona
 * 
 *         This Activity generates the tour depending on the spot chosen by the
 *         user. It displays a list view with all the sites in the tour ordered
 *         by the path to be taken.
 */

public class TourActivity extends Activity {

	final double latitudeTour1 = 29.976;
	final double longitudeTour1 = 31.134;
	final double latitudeTour2 = 29.87;
	final double longitudeTour2 = 31.22;
	final double latitudeTour3 = 30.05;
	final double longitudeTour3 = 31.21;
	double startLatitude, startLongitude;
	int tourNumber;
	final int ADD_PLACE_ID = 0;
	boolean newTour;

	ArrayList<Place> tourPlacesList;
	ArrayList<String> tourPlacesNames;
	CairodioDbAdapter dbHelper;

	private ImageButton mapBtn;
	private Button addBtn, editBtn, cancelBtn;
	private ListView Listview;
	private TourListAdapter tourAdapter;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.edit_tour_list);

		// Stopping background Service
		stopService(CairodioMapActivity.intent);

		init();
		getTourPlaces();
		getPlacesNames();

		tourAdapter = new TourListAdapter(this, tourPlacesNames);
		Listview.setAdapter(tourAdapter);
		updateListView();
	}

	@SuppressWarnings("unchecked")
	public void init() {

		// Obtaining start point and tour number from the bundle
		dbHelper = ((CairodioApplication) getApplication()).getAdapter();
		Bundle b = getIntent().getExtras();

		if (b != null) // To avoid incorrect starting of the activity
		{
			startLatitude = b.getDouble("Latitude");
			startLongitude = b.getDouble("Longitude");
			tourNumber = b.getInt("tourNumber");

			if (b.getBoolean("newTour")) {
				newTour = true;
				tourPlacesList = new ArrayList<Place>();

			} else {
				newTour = false;
				tourPlacesList = (ArrayList<Place>) b
						.getSerializable("TourPlaces");
			}
		}

		// navigates back to the map view
		mapBtn = (ImageButton) findViewById(R.id.tourMap);
		mapBtn.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				/*
				 * Intent intent = new Intent(TourActivity.this,
				 * CairodioMapActivity.class);
				 * intent.setFlags(intent.FLAG_ACTIVITY_CLEAR_TOP);
				 * intent.putExtra("TourPlaces", tourPlacesList);
				 * startActivity(intent);
				 */

				// Using startActivityForResult(..)

				Intent returnIntent = new Intent();
				returnIntent.putExtra("TourPlaces", tourPlacesList);
				setResult(RESULT_OK, returnIntent);
				finish();
			}
		});

		// switches to edit mode, by hiding the map and edit button
		// and shows the add and cancel button
		editBtn = (Button) findViewById(R.id.btnEdit);
		editBtn.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {

				tourAdapter.editMode = true;
				tourAdapter.notifyDataSetChanged();

				((Button) findViewById(R.id.btnCancel))
						.setVisibility(View.VISIBLE);

				((ImageButton) findViewById(R.id.tourMap))
						.setVisibility(View.GONE);

				((Button) findViewById(R.id.btnAdd))
						.setVisibility(View.VISIBLE);

				((Button) findViewById(R.id.btnEdit)).setVisibility(View.GONE);

			}
		});

		// navigates to the add place activity
		addBtn = (Button) findViewById(R.id.btnAdd);
		addBtn.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {

				Intent intent = new Intent().setClass(TourActivity.this,
						AddPlaceActivity.class);
				Bundle b = new Bundle();
				b.putStringArrayList(
						getString(R.string.add_place_activity_tour_places),
						tourPlacesNames);
				intent.putExtras(b);
				startActivityForResult(intent, ADD_PLACE_ID);

			}
		});

		// switches back to the non-editing mode, by doing the opposite of edit
		// button
		cancelBtn = (Button) findViewById(R.id.btnCancel);
		cancelBtn.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {

				tourAdapter.editMode = false;
				tourAdapter.notifyDataSetChanged();

				((Button) findViewById(R.id.btnCancel))
						.setVisibility(View.GONE);

				((ImageButton) findViewById(R.id.tourMap))
						.setVisibility(View.VISIBLE);

				((Button) findViewById(R.id.btnAdd)).setVisibility(View.GONE);

				((Button) findViewById(R.id.btnEdit))
						.setVisibility(View.VISIBLE);

			}
		});

		Listview = (ListView) findViewById(R.id.tourPlacesListView);
		tourPlacesNames = new ArrayList<String>();

	}

	/**
	 * @author Mona
	 * 
	 *  This method checks which spot was chosen by the user and accordinlgy performs a search 
	 *  to get all touristic places within a certain radius of that spot.
	 *  It then calls sortPlaces2() to arrange them.
	 */
	public void getTourPlaces() {

		TextView title = (TextView) findViewById(R.id.tourTitle);
		// Getting the places in the tour
		if (newTour) {
			if (tourNumber == 1) {
				tourPlacesList = dbHelper.getNearByPlacesWithRadius(
						latitudeTour1, longitudeTour1, 5000);
				title.setText(getString(R.string.tour_activity_tour_name_one));
			}
			if (tourNumber == 2) {
				tourPlacesList = dbHelper.getNearByPlacesWithRadius(
						latitudeTour2, longitudeTour2, 5000);
				title.setText(getString(R.string.tour_activity_tour_name_two));
			}
			if (tourNumber == 3) {
				tourPlacesList = dbHelper.getNearByPlacesWithRadius(
						latitudeTour3, longitudeTour3, 7000);
				title.setText(getString(R.string.tour_activity_tour_name_three));
			}
			// sortPlaces1();
			sortPlaces2();
		}

	}
	
	/**
	 * @author Mona
	 * 
	 * This method fills the tourPlacesNames list to be sent to the list view.
	 *  
	 */
	public void getPlacesNames() {
		for (int i = 0; i < tourPlacesList.size(); i++) {
			String name = (tourPlacesList.get(i)).getName();
			tourPlacesNames.add(name);
		}
	}

	/**
	 * @author Mona
	 * 
	 *  This method takes an object of type Place and a list of places
	 *  and returns the nearest place in the list to it.
	 *  
	 */
	public Place getNearestPlace(Place place, ArrayList<Place> places) {

		Place nearestPlace = new Place("", 0, 0);
		double minDist = 500000000;
		double dist;

		for (int i = 0; i < places.size(); i++) {
			dist = dbHelper.distFrom(place.getLatitude(), place.getLongitude(),
					(places.get(i)).getLatitude(),
					(places.get(i)).getLongitude());
			if (dist < minDist && dist != 0) {
				minDist = dist;
				nearestPlace.setName((places.get(i)).getName());
				nearestPlace.setLatitude((places.get(i)).getLatitude());
				nearestPlace.setLongitude((places.get(i)).getLongitude());
			}
		}
		// Toast.makeText(this, nearestPlace.getName(),
		// Toast.LENGTH_SHORT).show();
		return nearestPlace;
	}

	/**
	 * @author Mona
	 * 
	 *  This method removes a certain place from a list of places
	 *  
	 */
	public void removePlaceFrom(Place p, ArrayList<Place> places) {
		int n = places.size();
		for (int i = 0; i < n; i++) {
			if (((places.get(i)).getName()).equals(p.getName())) {
				places.remove(i);
				break;
			}

		}
	}

	/**
	 * @author Mona
	 * 
	 *  This method arranges the places of the tour. It starts with the nearest
	 *  place to the user's current location and keeps searching for the nearest
	 *   places to each place in the list iteratively.
	 *  
	 */
	public void sortPlaces2() {

		ArrayList<Place> sorted = new ArrayList<Place>();
		int n = tourPlacesList.size();
		Place nearest;
		Place startLocation = new Place("startLocation", startLatitude,
				startLongitude);
		nearest = getNearestPlace(startLocation, tourPlacesList);
		sorted.add(nearest);
		removePlaceFrom(nearest, tourPlacesList);

		for (int i = 0; i < n - 1; i++) {
			Place p = sorted.get(i);
			nearest = getNearestPlace(p, tourPlacesList);
			removePlaceFrom(nearest, tourPlacesList);
			sorted.add(nearest);
		}
		for (int j = 0; j < sorted.size(); j++) {
			tourPlacesList.add(sorted.get(j));
		}
	}

	/**
	 * @author Shokry
	 * 
	 *         Notify the datasource after it was filled with the tour places.
	 *         Then, add an action listener to the listview, if in edit mode it
	 *         deletes the place from the tour and recalculates it, else if not
	 *         in edit mode it navigates to the place detail view
	 */
	public void updateListView() {

		// tourAdapter.notifyDataSetChanged();

		Listview.setOnItemClickListener(new OnItemClickListener() {
			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {

				if (tourAdapter.editMode) {

					// REMOVE PLACE FROM TOUR AN RECALCULATE
					tourPlacesNames.remove(position);
					tourPlacesList.remove(position);
					sortPlaces2();
					tourAdapter.notifyDataSetChanged();

				} else {

					String placeName = (String) ((TextView) (view
							.findViewById(R.id.tourItem))).getText();
					int placeID = dbHelper.getID(placeName);

					// NAVIGATE TO AUDIO CLIPS
					Bundle b = new Bundle();
					b.putInt("placeId", placeID);
					b.putString("placeName", placeName);
					Intent intent = new Intent(TourActivity.this,
							AudioClipsActivity.class);
					intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
					intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
					intent.putExtras(b);
					startActivity(intent);
				}

			}
		});

	}

	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		switch (requestCode) {
		case ADD_PLACE_ID:
			if (resultCode == RESULT_OK) {
				int placeID = data.getIntExtra(
						getString(R.string.add_place_activity_place_id), -1);

				Place addedPlace = dbHelper.getPlace(placeID);
				tourPlacesNames.add(addedPlace.getName());
				tourPlacesList.add(addedPlace);
				sortPlaces2();
				tourAdapter.notifyDataSetChanged();

				Toast.makeText(this, R.string.tour_activity_new_place_added,
						Toast.LENGTH_LONG).show();
				break;
			}
		}
	}

	public void onStart() {
		super.onStart();
		stopService(CairodioMapActivity.intent);

	}

	@Override
	public void onPause() {
		super.onPause();
		startService(CairodioMapActivity.intent);
	}

	@Override
	public void onResume() {
		super.onResume();
		tourAdapter.notifyDataSetChanged();
	}

	@Override
	public void onStop() {
		super.onStop();
		
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		stopService(CairodioMapActivity.intent);	}
}